if(!jsx3.lang.Class.forName("tibco.admin.enterpriseAssets.userMgt.groups.Master")) {
    /**
     *
     */
    jsx3.lang.Package.definePackage("tibco.admin.enterpriseAssets.userMgt.groups", function (groups) {
    });

    /**
     *
     */
    jsx3.lang.Class.defineClass("tibco.admin.enterpriseAssets.userMgt.groups.Master",
            jsx3.gui.LayoutGrid,
            null,
            function (master) {
                master.prototype.initialize = function() {
                    tibco.admin.util.Log.USERMGT.trace("tibco.admin.enterpriseAssets.userMgt.groups.Master#initialize")
                    this.selected = null
                    this.GET_SON_ALREADY = "sonexist";
                    this.subscribeAll();


                    if(jsx3.lang.Class.forName("tibco.admin.enterpriseAssets.userMgt.window.Window")) {
                        // set the window instance
                        this.window = this.getAncestorOfType(tibco.admin.enterpriseAssets.userMgt.window.Window)
                        if(this.window) {
                            this.setWindowId(this.window.getId());
                        }
                    }
                    // set the matrix
                    this.mtx = this.getDescendantOfName("mtxMaster_24_F");

                    var me = this;
                    this.mtx.recordSelected = function(strRECORDIDS) {
                        me.recordSelected(strRECORDIDS);
                    };
                    setTimeout(function(){me.callgetChildGroups("root")} ,200)
                }

                master.prototype.subscribeAll = function() {
                    tibco.admin.PubSub.subscribe(tibco.admin.enterpriseAssets.userMgt.EventID.ADD_ITEM_SUCCESS, this, this.selectAdded);
                    tibco.admin.PubSub.subscribe(tibco.admin.enterpriseAssets.userMgt.EventID.EDIT_ITEM_SUCCESS, this, this.refreshMasterOnEdit);
                    tibco.admin.PubSub.subscribe(tibco.admin.enterpriseAssets.userMgt.EventID.ADD_ITEM_CANCELED, this, this.refreshSelected);
                    tibco.admin.PubSub.subscribe(tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_REMOVED, this, this.refreshMaster);
                }

                master.prototype.unsubscribeAll = function() {
                    tibco.admin.PubSub.unsubscribe(tibco.admin.enterpriseAssets.userMgt.EventID.ADD_ITEM_SUCCESS, this);
                    tibco.admin.PubSub.unsubscribe(tibco.admin.enterpriseAssets.userMgt.EventID.EDIT_ITEM_SUCCESS, this);
                    tibco.admin.PubSub.unsubscribe(tibco.admin.enterpriseAssets.userMgt.EventID.ADD_ITEM_CANCELED, this);
                    tibco.admin.PubSub.unsubscribe(tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_REMOVED, this);
                }

                master.prototype.setWindowId = function(strId) {
                    this.windowId = strId
                }

                master.prototype.getWindowId = function() {
                    return this.windowId
                }

                master.prototype.setSelectedRecord = function(strRECORDID) {
                    this.selected = strRECORDID
                }

                master.prototype.getSelectedRecord = function() {
                    return this.selected
                }

                master.prototype.setListButtonsEnabled = function(intEnabled, bRepaint) {
                    this.getDescendantOfName("btnRootGroup_24_F").setEnabled(intEnabled, true);
                }

                master.prototype.setEdittButtonsEnabled = function(intEnabled, bRepaint) {
                    if(this.isRealmWriteable) {
                        this.getDescendantOfName("btnSubGroup_24_F").setEnabled(intEnabled, bRepaint)
                        this.getDescendantOfName("btnGroupDelete_24_F").setEnabled(intEnabled, bRepaint)
                    }
                }

                /**
                 * called when a user in user list is selected. publishes an event object (javascript object) with the
                 * following named properties: subject(tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_SELECTED):
                 * windowId(id of the parent window instance); userId(userId); isWriteable(boolean) ;
                 * isGetGroupsFprUserEfficient(boolean)
                 *
                 *@param strRecordId {String} ?the jsxid attribute of the data record to return.(selected item)
                 */
                master.prototype.publishSelect = function(strRECORDIDS) {
                    tibco.admin.util.Log.USERMGT.trace(" master.prototype.publishSelect strRECORDIDS = " + strRECORDIDS + " strRECORDIDS.length = " + strRECORDIDS.length)
                    if (strRECORDIDS.length != 1) {
                        var msg = new Object();
                        msg.subject = tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_MULTISELECT;
                        msg.windowId = this.getWindowId();
                        msg.master = "tibco.admin.enterpriseAssets.userMgt.groups.Master"
                        tibco.admin.PubSub.publish(msg);
                        return;
                    }
                    var strRowID = strRECORDIDS[0];
                    this.setSelectedRecord(strRowID);
                    var record = this.mtx.getXML().selectSingleNode("//record[@jsxid ='" + strRowID + "']");
                    tibco.admin.util.Log.USERMGT.trace("----------------------record = " + record)
                    if (record) {
                        var msg = new Object();
                        msg.subject = tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_SELECTED;
                        msg.windowId = this.getWindowId();
                        msg.groupId = record.getAttribute("jsxid");
                        tibco.admin.util.Log.USERMGT.trace("----------------------msg.groupId  = " + msg.groupId)
                        msg.groupName = record.getAttribute("name");
                        msg.groupDesc = (dummy = record.getAttribute("description"))?dummy:"";
                        msg.isWriteable = (record.getAttribute("isWriteable") == 'true');
                        msg.isGetUsersForGroupEfficient = (record.getAttribute("isGetUsersForGroupEfficient") == 'true')?true:false;
                        msg.isRealmWriteable = this.isRealmWriteable;
                        msg.strPath = "tibco/admin/enterpriseAssets/userMgt/window/groups/ui/groupDetail.xml";
                        tibco.admin.PubSub.publish(msg);
                    }
                }

                master.prototype.addNewUser = function(strPath, isSubGroup) {
                    if(!isSubGroup)
                        this.mtx.deselectAllRecords()
                    var msg = new Object();
                    msg.subject = tibco.admin.enterpriseAssets.userMgt.EventID.ADD_ITEM_REQUIRED;
                    msg.strPath = strPath;
                    msg.windowId = this.getWindowId();
                    if(isSubGroup) {
                        msg.parentItem = this.getSelectedRecord()
                    }
                    tibco.admin.PubSub.publish(msg)
                }

                master.prototype.selectAdded = function(objEvent) {
                    // refresh the user list
                    tibco.admin.util.Log.USERMGT.trace("tibco.admin.enterpriseAssets.userMgt.groups.Master#selectAdded  " + objEvent.windowId + "  " + this.getWindowId() + "   " + objEvent.isRetained)
                    if(objEvent.refresh) {
                        this.publishSelect(this.mtx.getSelectedIds());
                        return;
                    }
                    if(objEvent.windowId == this.getWindowId() && !objEvent.isRetained) {
                        this.mtx.deselectAllRecords();
                        var parentNode = this.mtx.getRecordNode(objEvent.parentItem)
                        if(parentNode) {
                            if(parentNode.getAttribute(this.GET_SON_ALREADY) == "1") {
                                this.setSelectedRecord(objEvent.addedItem)
                                this.mtx.selectRecord(objEvent.addedItem)
                                tibco.admin.util.Log.USERMGT.trace("............................................selectAdded in first if 0")
                                this.callgetChildGroups("added", objEvent.addedItem, objEvent.parentItem)
                                tibco.admin.util.Log.USERMGT.trace("............................................selectAdded in first if 1")
                            }
                            else {
                                tibco.admin.util.Log.USERMGT.trace("............................................selectAdded in first if else 2")
                                this.setSelectedRecord(objEvent.parentItem)
                                this.mtx.selectRecord(objEvent.parentItem)
                                this.callgetChildGroups()
                            }

                        }
                        else {
                            tibco.admin.util.Log.USERMGT.trace("............................................selectAdded in else")
                            this.setSelectedRecord(objEvent.addedItem)
                            tibco.admin.util.Log.USERMGT.trace("............................................selectAdded in else this.setSelectedRecord 1 = " + this.getSelectedRecord())
                            this.mtx.selectRecord(objEvent.addedItem)
                            tibco.admin.util.Log.USERMGT.trace("............................................selectAdded in else this.setSelectedRecord 2 = " + this.getSelectedRecord())
                            this.callgetChildGroups("added", objEvent.addedItem, objEvent.parentItem)
                        }
                        this.setEdittButtonsEnabled(jsx3.gui.Form.STATEENABLED, true)
                    }
                }

                master.prototype.refreshSelected = function() {
                    if(this.getSelectedRecord())
                        this.mtx.selectRecord(this.getSelectedRecord());
                }

                master.prototype.callremoveGroups = function() {
                    tibco.admin.Main.getServer().getCache().setDocument("XMLCacheMaster_24_F", this.mtx.getXML());
                    if (this.mtx.getSelectedIds().length > 0) {
                        var objService = tibco.admin.Main.loadService("tibco.admin", "tibco/admin/enterpriseAssets/userMgt/window/groups/rules/removeGroups.xml", "removeGroups", "Remove Groups");
                        //subscribe and call
                        objService.subscribe(jsx3.net.Service.ON_SUCCESS, this, this.onremoveGroupsSuccess);
                        objService.subscribe(jsx3.net.Service.ON_ERROR, this, this.onremoveGroupsError);
                        objService.subscribe(jsx3.net.Service.ON_INVALID, this, this.onremoveGroupsInvalid);
                        objService.setEndpointURL(tibco.admin.util.ServiceHelper.getUserMgtEndpointURL());
                        objService.doCall();
                    }

                };

                master.prototype.onremoveGroupsSuccess = function(objEvent) {
                    this.setSelectedRecord(null)
                    var msg = new Object();
                    msg.subject = tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_REMOVED
                    msg.windowId = this.getWindowId();
                    msg.master = "tibco.admin.enterpriseAssets.userMgt.groups.Master"
                    tibco.admin.PubSub.publish(msg);
                    tibco.admin.util.Log.USERMGT.trace("Success", "The service call was successful.");
                };

                master.prototype.onremoveGroupsError = function(objEvent) {
                    var myStatus = objEvent.target.getRequest().getStatus();
                    tibco.admin.util.Log.USERMGT.error("Error, The service call failed. The HTTP Status code is: " + myStatus);
                };

                master.prototype.onremoveGroupsInvalid = function(objEvent) {
                    tibco.admin.util.Log.USERMGT.error("Invalid, The following message node just failed validation:\n\n" + objEvent.message);
                };

                master.prototype.doRefresh = function() {
                    this.callgetChildGroups("refresh")
                    this.setEdittButtonsEnabled(jsx3.gui.Form.STATEDISABLED, true)
                }

                master.prototype.refreshMaster = function(objEvent) {
                    if(!objEvent.isRetained && objEvent.master == "tibco.admin.enterpriseAssets.userMgt.groups.Master") {
                        this.callgetChildGroups("root")
                        this.setEdittButtonsEnabled(jsx3.gui.Form.STATEDISABLED, true)
                    }
                }

                master.prototype.refreshMasterOnBtnClick = function() {
                    if(this.getSelectedRecord()) {
                        this.callgetChildGroups("refresh")
                    }
                    else {
                        this.callgetChildGroups("root")
                    }
                }

                master.prototype.refreshMasterOnEdit = function(objEvent) {
                    if(!objEvent.isRetained && objEvent.windowId == this.getWindowId()) {
                        this.callgetChildGroups("refreshEdited")
                    }
                }


                //====================GET CHILD GROUPS====================
                master.prototype.callgetChildGroups = function(action, addedgroupid, parentgroupid) {
                    if(action == "refresh") {
                        tibco.admin.util.Log.USERMGT.trace("---------------------------refresh ::::::::::: action, addedgroupid, parentgroupid " + action + " " + addedgroupid + " " + parentgroupid)
                        var objService = tibco.admin.Main.loadService("tibco.admin", "tibco/admin/enterpriseAssets/userMgt/window/groups/rules/getChildGroups.xml", "getChildGroups", "Get Child Groups");
                        objService.subscribe(jsx3.net.Service.ON_SUCCESS, this, this.ongetChildGroupsSuccess);
                        objService.parentgroupid = this.getSelectedRecord()
                    }
                    else if(action == "root") {
                        tibco.admin.util.Log.USERMGT.trace("---------------------------root ::::::::::: action, addedgroupid, parentgroupid " + action + " " + addedgroupid + " " + parentgroupid)
                        var objService = tibco.admin.Main.loadService("tibco.admin", "tibco/admin/enterpriseAssets/userMgt/window/groups/rules/getChildGroups.xml", "getChildGroups", "Get Child Groups");
                        objService.subscribe(jsx3.net.Service.ON_SUCCESS, this, this.ongetChildGroupsRootSuccess);
                        objService.parentgroupid = this.getSelectedRecord()
                    }
                    else if(action == "added") {
                        tibco.admin.util.Log.USERMGT.trace("---------------------------added ::::::::::: action, addedgroupid, parentgroupid " + action + " " + addedgroupid + " " + parentgroupid)
                        var objService = tibco.admin.Main.loadService("tibco.admin", "tibco/admin/enterpriseAssets/userMgt/window/groups/rules/getChildGroups.xml", "getChildGroups", "Get Child Groups");
                        objService.subscribe(jsx3.net.Service.ON_SUCCESS, this, this.ongetChildGroupsAddedSuccess);
                        objService.parentgroupid = parentgroupid
                        objService.addedgroupid = addedgroupid
                    }
                    else if(action == "refreshEdited") {
                        tibco.admin.util.Log.USERMGT.trace("---------------------------refreshEdited ::::::::::: action, addedgroupid, parentgroupid " + action + " " + addedgroupid + " " + parentgroupid)
                        if(this.getSelectedRecord()) {
                            var objService = tibco.admin.Main.loadService("tibco.admin", "tibco/admin/enterpriseAssets/userMgt/window/groups/rules/getChildGroups.xml", "getChildGroups", "Get Child Groups");
                            var parentid = this.mtx.getRecordNode(this.getSelectedRecord()).getParent().getAttribute("jsxid")
                            if(parentid == "jsxroot") {
                                objService.subscribe(jsx3.net.Service.ON_SUCCESS, this, this.ongetChildGroupsRootSuccess);
                                objService.parentgroupid = null;
                            }
                            else {
                                objService.subscribe(jsx3.net.Service.ON_SUCCESS, this, this.ongetChildGroupsSuccess);
                                objService.parentgroupid = parentid
                            }
                        }
                    }
                    else {
                        var parentNode = this.mtx.getRecordNode(this.getSelectedRecord());
                        if(parentNode.getAttribute(this.GET_SON_ALREADY) != "1") {
                            var objService = tibco.admin.Main.loadService("tibco.admin", "tibco/admin/enterpriseAssets/userMgt/window/groups/rules/getChildGroups.xml", "getChildGroups", "Get Child Groups");
                            objService.subscribe(jsx3.net.Service.ON_SUCCESS, this, this.ongetChildGroupsSuccess);
                            objService.parentgroupid = this.getSelectedRecord()
                        }
                        else {
                            this.publishSelect(this.mtx.getSelectedIds());
                        }
                    }
                    if(objService) {
                        objService.subscribe(jsx3.net.Service.ON_ERROR, this, this.ongetChildGroupsError);
                        objService.subscribe(jsx3.net.Service.ON_INVALID, this, this.ongetChildGroupsInvalid);
                        objService.setEndpointURL(tibco.admin.util.ServiceHelper.getUserMgtEndpointURL());
                        objService.doCall();
                    }
                };

                master.prototype.ongetChildGroupsSuccess = function(objEvent) {
                    this.actionOngetChildGroupsSuccess(objEvent, true)
                };

                master.prototype.ongetChildGroupsRootSuccess = function(objEvent) {
                    this.actionOngetChildGroupsSuccess(objEvent, false)
                }

                master.prototype.ongetChildGroupsAddedSuccess = function(objEvent) {
                    this.actionOngetChildGroupsSuccess(objEvent, true, true)
                };

                master.prototype.actionOngetChildGroupsSuccess = function(objEvent, appendChildren, appendAddedChild, refreshEdited) {
                    var responseXML = objEvent.target.getInboundDocument();
                    var transformXSL = new jsx3.xml.Document().load(tibco.admin.Main.resolveURI("tibco.admin", "tibco/admin/enterpriseAssets/userMgt/window/groups/xsl/getChildGroups.xsl"));
                    var xsltprocessor = new jsx3.xml.Processor(responseXML, transformXSL)
                    var transformedDocument = xsltprocessor.transformToObject();
                    if(appendChildren) {
                        if(appendAddedChild) {
                            var addedRecord = transformedDocument.selectSingleNode("//record[@jsxid ='" + objEvent.target.addedgroupid + "' ]")
                            if(objEvent.target.parentgroupid) {
                                var parentNode = this.mtx.getRecordNode(objEvent.target.parentgroupid);
                            }
                            else {
                                var parentNode = this.mtx.getRecordNode("jsxroot");
                            }
                            parentNode.appendChild(addedRecord.cloneNode());
                        }
                        else {
                            var nodeList = transformedDocument.getChildNodes(true);
                            var parentNode = this.mtx.getRecordNode(objEvent.target.parentgroupid);
                            parentNode.setAttribute(this.GET_SON_ALREADY, "1");
                            parentNode.removeChildren();

                            for(var i = 0; i < nodeList.size(); i++) {
                                parentNode.appendChild(nodeList.get(i));
                            }
                        }
                    }
                    else {
                        this.mtx.setSourceXML(transformedDocument)
                        if(!this.getSelectedRecord()) {
                            this.getDescendantOfName("btnSubGroup_24_F").setEnabled(jsx3.gui.Form.STATEDISABLED, true)
                        }
                    }

                    var state = (objEvent.target.isRealmWriteable == "true")? jsx3.gui.Form.STATEENABLED : jsx3.gui.Form.STATEDISABLED ;
                    this.isRealmWriteable = (objEvent.target.isRealmWriteable == "true");
                    this.setListButtonsEnabled(state, true);
                    tibco.admin.util.Log.USERMGT.trace("---------------------------------- before if this.getSelectedRecord() = " + this.getSelectedRecord())
                    if(this.getSelectedRecord()) {
                        tibco.admin.util.Log.USERMGT.trace("---------------------------in if this.getSelectedRecord() = " + this.getSelectedRecord())
                        if(appendAddedChild) {
                            if(parentNode.getAttribute("jsxopen") != "1")
                                this.mtx.toggleItem(objEvent.target.parentgroupid, true)
                        }
                        // select the detalis for this selected
                        var array = new Array
                        array[0] = this.getSelectedRecord()
                        this.publishSelect(array)
                        this.mtx.selectRecord(this.getSelectedRecord())
                    }
                    this.mtx.repaintData()
                };

                master.prototype.ongetChildGroupsError = function(objEvent) {
                    var myStatus = objEvent.target.getRequest().getStatus();
                    tibco.admin.util.Log.USERMGT.error("Error, The service call failed. The HTTP Status code is: " + myStatus);
                };

                master.prototype.ongetChildGroupsInvalid = function(objEvent) {
                    tibco.admin.util.Log.USERMGT.error("Invalid, The following message node just failed validation:\n\n" + objEvent.message);
                };

                master.prototype.recordSelected = function(strRECORDIDS) {
                    strRECORDIDS = this.mtx.getSelectedIds()
                    tibco.admin.util.Log.USERMGT.trace("master.prototype.recordSelecte  " + strRECORDIDS)
                    if(strRECORDIDS.length > 0) {
                        // enable delete button
                        if(this.isRealmWriteable)
                            this.getDescendantOfName("btnGroupDelete_24_F").setEnabled(jsx3.gui.Form.STATEENABLED, true);
                        if(strRECORDIDS.length == 1) {
                            // enabale  new sub Group
                            if(this.isRealmWriteable)
                                this.getDescendantOfName("btnSubGroup_24_F").setEnabled(jsx3.gui.Form.STATEENABLED, true);
                            this.setSelectedRecord(strRECORDIDS);
                            this.callgetChildGroups();
                        }
                        else {
                            // disable new sub group
                            this.getDescendantOfName("btnSubGroup_24_F").setEnabled(jsx3.gui.Form.STATEDISABLED, true);
                            var msg = new Object();
                            msg.subject = tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_MULTISELECT;
                            msg.windowId = this.getWindowId();
                            msg.master = "tibco.admin.enterpriseAssets.userMgt.groups.Master"
                            tibco.admin.PubSub.publish(msg);
                        }

                    }
                    else {
                        // disable all 2 buttons
                        this.getDescendantOfName("btnSubGroup_24_F").setEnabled(jsx3.gui.Form.STATEDISABLED, true)
                        this.getDescendantOfName("btnGroupDelete_24_F").setEnabled(jsx3.gui.Form.STATEDISABLED, true)
                        this.setSelectedRecord(null);
                        var msg = new Object();
                        msg.subject = tibco.admin.enterpriseAssets.userMgt.EventID.MASTER_ROW_MULTISELECT;
                        msg.windowId = this.getWindowId();
                        msg.master = "tibco.admin.enterpriseAssets.userMgt.groups.Master"
                        tibco.admin.PubSub.publish(msg);
                    }
                }

            });
}
